home *** CD-ROM | disk | FTP | other *** search
/ Chip 2007 January, February, March & April / Chip-Cover-CD-2007-02.iso / Pakiet bezpieczenstwa / mini Pentoo LiveCD 2006.1 / mpentoo-2006.1.iso / livecd.squashfs / usr / lib / metasploit / msfupdate < prev    next >
Text File  |  2006-06-30  |  20KB  |  777 lines

  1. #!/usr/bin/perl
  2. ###############
  3.  
  4. require 5.6.0;
  5. use strict;
  6. use vars qw{$SSL_SUPPORT};
  7.  
  8. use FindBin qw{$RealBin};
  9. use lib "$RealBin/lib";
  10. use Digest::Perl::MD5 qw{md5_hex};
  11.  
  12. use Getopt::Std;
  13. use IO::Socket;
  14. use IO::Select;
  15. use POSIX;
  16.  
  17. no utf8;
  18. no locale;
  19.  
  20. my $VERSION      = '$Revision: 1.45 $';
  21. my $FRAMEWORK    = '2.6';
  22. my ($REV)        = $VERSION =~ m/\$Revisio.:\s+([^\s]+)/;
  23.  
  24. my $UPDATE_HOST  = 'metasploit.com';
  25. my $UPDATE_PATH  = '/projects/Framework/updates/msfupdate.html';
  26. my $SSL_VERIFIED = 0;
  27. my $SSL_ISSUER   = '/C=US/ST=Texas/L=San Antonio/O=The Metasploit Project/OU=Development/CN=Metasploit CA/emailAddress=cacert@metasploit.com';
  28. my $SSL_CERTS    = "$RealBin/docs";
  29. my $OPSYS        = $^O;
  30.  
  31. select(STDOUT); $|++;
  32.  
  33. # Check for buggy versions of perl with utf-8 locale set
  34. BrokenUTF8();
  35.  
  36. # Determine if SSL support is enabled
  37. BEGIN
  38. {
  39.     if (eval "require Net::SSLeay")
  40.     {
  41.         Net::SSLeay->import();
  42.         Net::SSLeay::load_error_strings();
  43.         Net::SSLeay::SSLeay_add_ssl_algorithms();
  44.         Net::SSLeay::randomize();
  45.         $SSL_SUPPORT++;
  46.     }
  47. }
  48.  
  49. my %opts;
  50. getopts('hrvusmaxfOp:', \%opts);
  51.  
  52. if ($opts{v}) {
  53.     print "Msfupdate Version: $REV\n";
  54.     print "Framework Version: $FRAMEWORK\n";
  55.     exit(0);
  56. }
  57.  
  58. if ($opts{h} || (! $opts{m} && ! $opts{r} && ! $opts{u} && ! $opts{U})) {
  59.     Usage();
  60. }
  61.  
  62. if ($opts{O}) {
  63.    $OPSYS = 'paranoid';
  64. }
  65.  
  66. chdir($RealBin);
  67.  
  68. my $proxy = $opts{'p'};
  69. my ($old_data, $now_data, $new_data);
  70. my ($old, $now, $new);
  71. my ($mod, $upx, $upd);
  72.  
  73. print "\n";
  74. print "+ -- --=[ msfupdate v$FRAMEWORK [revision $REV]\n\n";
  75. print "[*] Calculating local file checksums, please wait...\n";
  76. $now_data = ScanFiles('.');
  77. print "\n";
  78.  
  79. if (! -r '.current') {
  80.     WriteFile('.current', $now_data);
  81.     $old_data = $now_data;
  82. else {
  83.     $old_data = ReadFile('.current');
  84. }
  85.  
  86. if ($opts{r}) {
  87.     print "[*] The local file hash has been rebuilt\n";
  88.     WriteFile('.current', $now_data);
  89.     exit(0);
  90. }
  91.  
  92. # Allow the user to disable SSL mode entirely
  93. if ($opts{f}) {
  94.     $SSL_SUPPORT = 0;
  95. }
  96.  
  97. # Display a big nasty warning for non-SSL unless -x is specified
  98. if ($opts{u} || $opts{U}) {
  99.     if (! $opts{x} && ! $SSL_SUPPORT) {
  100.         print "[*] WARNING: The Net::SSLeay module is not installed. The update\n";
  101.         print "    process will fall back to plain HTTP, this may allow a \n";
  102.         print "    malicious attacker to inject hostile code into your system.\n";
  103.         print "\n";
  104.         print "Continue anyways (yes or no) ";
  105.         
  106.         my $resp;
  107.         while ($resp !~ /yes|no/i) {
  108.             print "> ";
  109.             $resp = <STDIN>;
  110.             chomp($resp);
  111.         }
  112.         print "\n";
  113.         
  114.         if ($resp !~ /yes/i) {
  115.             print "[*] The update process has been cancelled\n";
  116.             exit(0);
  117.         }
  118.     }
  119.     
  120.     $new_data = DownloadFile($UPDATE_HOST, "$UPDATE_PATH/.current", $proxy);
  121. }
  122.  
  123. $now = Hashit($now_data);
  124. $old = Hashit($old_data);
  125. $new = Hashit($new_data);
  126.  
  127. $mod = Diff($old, $now);
  128. $upx = Diff($old, $new);
  129. $upd = Diff($now, $new);
  130.  
  131. if ($opts{m}) {
  132.     if (! keys(%{$mod})) {
  133.         print "[*] No modifications since the last update\n";
  134.         exit(0);
  135.     }
  136.     
  137.     print "[*] Modifications since the last update:\n";
  138.     foreach (sort keys(%{$mod})) {
  139.         print "\t".$mod->{$_}."\t$_\n";
  140.     }
  141.     print "\n";
  142.     exit(0);
  143. }
  144.  
  145. # Strip this list down to just modifications
  146. foreach (keys(%{$mod})) {
  147.     if ($mod->{$_} ne 'Mod') {
  148.         delete($mod->{$_});
  149.     }
  150. }
  151.  
  152. if (! $new_data) {
  153.     print "[*] Could not obtain the current version information from the update server\n";
  154.     exit(0);
  155. }
  156.  
  157. my $mver = CheckVersion();
  158.  
  159. if ( ($opts{u} || $opts{U}) && ! $mver) {
  160.     print "[*] Could not determine the current Framework version.\n";
  161.     exit(0);
  162. }
  163.  
  164. if ($mver && $mver ne $FRAMEWORK) {
  165.  
  166.     if (! $opts{U}) {
  167.         print "[*] Version $mver of the Metasploit Framework is now available.\n";
  168.         print "    - http://metasploit.com/projects/Framework/downloads.html\n\b\n";
  169.     }
  170.     else {
  171.         print "[*] Starting upgrade process for version $mver...\n\n";
  172.     }
  173. }
  174.  
  175. if ($opts{U} && $mver && $mver eq $FRAMEWORK) {
  176.     print "[*] No version upgrade is necessary.\n";
  177.     exit(0);
  178. }
  179.  
  180. # Upgrade to a new major release version...
  181. if ($opts{U}) {
  182.   
  183.     my $backupdir = 'backup_'. $FRAMEWORK;
  184.     
  185.     print "[*] WARNING: You are about to upgrade to a new major version of the\n";
  186.     print "    Metasploit Framework. This process involves removing the current\n";
  187.     print "    installation and downloading the new version, one file at a time.\n";
  188.     print "    This process is slow and somewhat prone to failure. If you encounter\n";
  189.     print "    any problems during the download, you *should* be able to simply\n";
  190.     print "    restart msfupdate with the -u parameter\n\n";
  191.     
  192.     print "    If you have modified any of the files in the Framework directory,\n";
  193.     print "    these will be saved to $backupdir. The same applies for any modules\n";
  194.     print "    that you have added to this Framework installation. After the update\n";
  195.     print "    is complete, you should be able to copy these modules from the\n";
  196.     print "    backup directory ($backupdir) into the appropriate directories\n";
  197.     print "    in the new installation.\n\n";
  198.  
  199.     print "    If you are using FreeBSD or any other operating that maintains a\n";
  200.     print "    package for the Framework, we recommend that you use the system\n";
  201.     print "    package manager to upgrade\n\n";
  202.     
  203.     print "    Please type 'yes' to initiate the upgrade process.\n";
  204.     print "Continue? (yes or no) ";
  205.     
  206.     my $resp;
  207.     while ($resp !~ /yes|no/i) {
  208.         print "> ";
  209.         $resp = <STDIN>;
  210.         chomp($resp);
  211.     }
  212.     if ($resp =~ /no/i) {
  213.         exit(0);
  214.     }
  215.     
  216.     delete($now->{'./msfupdate'});
  217.     delete($new->{'./msfupdate'});
  218.     delete($mod->{'./msfupdate'});
  219.     delete($upd->{'./msfupdate'});
  220.  
  221.     print "[*] Backing up modified files to $backupdir...\n";
  222.     
  223.     # Backup framework files that the user modified
  224.     foreach my $file (keys %{$mod} ) {
  225.         print "    --- MOD $file\n";
  226.         my $data = ReadFile($file);
  227.         WriteFile($backupdir .'/'. $file , $data);
  228.     }
  229.     
  230.     # Backup files that the user created
  231.     foreach my $file (keys %{$upd} ) {
  232.         next if $upd->{$file} ne 'Del';
  233.         print "    --- USR $file\n";
  234.         my $data = ReadFile($file);
  235.         WriteFile($backupdir .'/'. $file , $data);
  236.     }   
  237.     
  238.     print "[*] Removing the current installation...\n";
  239.  
  240.     # Do not remove these files since we need them to update...
  241.     my %docs_save = ('./docs/7f8d5320.0' => 1, './docs/cacert.pem' => 1);
  242.  
  243.     # Remove all files that are part of the framework
  244.     foreach my $file (keys %{$now}) {
  245.         next if exists($docs_save{$file});
  246.         unlink($file);
  247.     }
  248.  
  249.     # Remove all directories but 'docs'
  250.     foreach my $dir (split(/\n/, ScanDirs('.', 0))) {
  251.         next if $dir eq './docs';
  252.         system("rm", "-rf", $dir);
  253.     }
  254.     
  255.     # Bump up the framework version
  256.     $FRAMEWORK = $mver;
  257.     
  258.     # Download the file list for the new framework version
  259.     $new_data = DownloadFile($UPDATE_HOST, "$UPDATE_PATH/.current", $proxy);
  260.  
  261.     # Rebuild the tables
  262.     $new = Hashit($new_data);
  263.     $now = {};
  264.     $old = {};
  265.  
  266.     $mod = Diff($old, $now);
  267.     $upx = Diff($old, $new);
  268.     $upd = Diff($now, $new);
  269.     
  270.     # Configure some options
  271.     $opts{a}++;
  272. }
  273.  
  274.  
  275.  
  276.  
  277. # They modified something, ask them what they want to do with it
  278. if (! $opts{a} && keys(%{$mod})) {  
  279.     print "[*] You have modified the following Framework components:\n\n";
  280.     foreach (sort(keys(%{$mod}))) {
  281.         print "\t".$_."\n";
  282.     }
  283.     print "\n";
  284.     print "    Would you like to preserve these changes? If you say no, all\n";
  285.     print "    local modifications will be overwritten by the update process.\n";
  286.     print "\n";
  287.     print "Preserve modifications (yes or no) ";
  288.     my $resp;
  289.     while ($resp !~ /yes|no/i) {
  290.         print "> ";
  291.         $resp = <STDIN>;
  292.         chomp($resp);
  293.     }
  294.     if ($resp =~ /no/i) {
  295.         $mod = {};
  296.     }
  297.     print "\n";
  298. }
  299.  
  300. foreach (keys(%{$upd})) {
  301.     # Do not remove user-created files
  302.     if ($upd->{$_} eq 'Del') {
  303.         delete($upd->{$_});
  304.     }
  305.  
  306.     # Ignore updates we already have
  307.     if ($now->{$_} eq $new->{$_}) {
  308.         delete($upd->{$_});
  309.     }    
  310. }
  311.  
  312.  
  313. # Ignore locally modified files when -a is supplied
  314. if ($opts{a}) {
  315.     $mod = {};
  316. }
  317.  
  318. # After all of this stuff, this is what we have
  319. # - $mod is a table of anything the user wants to keep
  320. # - $upd is a table of everything online new or updated
  321.  
  322.  
  323. # The plan of attack is:
  324. # - Iterate through each item in $upd, if there is a match in
  325. #   $mod, we print a message and ignore the download for it.
  326. #   We will delete anything with the Del status set in this
  327. #   table. 
  328. # - Once we have identified an update, we try to download it.
  329. #   If an error occurs, either because the download fails or
  330. #   the md5 does no match.
  331. #
  332. # - After all files have been processed, we rebuild the local
  333. #   .current file and get ready for the next update.
  334. #
  335.  
  336. if (! keys(%{$upd})) {
  337.     print "[*] No new updates are available\n";
  338.     exit(0);
  339. }
  340.  
  341. print "[*] Online Update Task Summary\n\n";
  342. foreach my $entry (sort keys(%{$upd})) {
  343.     next if $opts{U};
  344.     
  345.     if ($mod->{$entry}) {
  346.         print "\tIgnore: $entry\n";
  347.     }
  348.     else {
  349.         print "\tUpdate: $entry\n";
  350.     }
  351. }
  352. print "\n";
  353.  
  354. exit(0) if $opts{s};
  355.  
  356. if (! $opts{a}) {
  357.     print "Continue? (yes or no) ";
  358.     my $resp;
  359.     while ($resp !~ /yes|no/i) {
  360.         print "> ";
  361.         $resp = <STDIN>;
  362.         chomp($resp);
  363.     }
  364.     print "\n";
  365.     if ($resp !~ /yes/i) {
  366.         exit(0);
  367.     }
  368. }
  369.  
  370. my @tasks = sort(keys(%{$upd}));
  371.  
  372. # Force msfupdate to downloaded first...
  373. if ($opts{U}) {
  374.     unshift(@tasks, './msfupdate');
  375.     unshift(@tasks, './lib/Digest/Perl/MD5.pm');
  376. }
  377.  
  378. my $upd_tot = scalar(@tasks);
  379. my $upd_cur = 0;
  380.  
  381. print "\n";
  382. print "[*] Starting online update of $upd_tot file(s)...\n\n";
  383. foreach my $entry (@tasks) {
  384.     if ($mod->{$entry}) {
  385.         next;
  386.     } 
  387.     my $data = DownloadFile($UPDATE_HOST, "$UPDATE_PATH/$entry", $proxy);
  388.     if ($new->{$entry} ne md5_hex($data)) {
  389.         print "$entry: ". $new->{$entry} ." != ". md5_hex($data) ."\n";
  390.         my $errmsg = $data ? 'checksum mismatch' : 'download failed';
  391.         print "[*] Failed to update $entry: $errmsg\n";
  392.         next;
  393.     }
  394.     
  395.     # overwrite the local file O_o
  396.     WriteFile($entry, $data);
  397.     
  398.     # set it executable since we dont track permissions
  399.     chmod(0755, $entry);
  400.     
  401.     printf("[%.4d/%.4d - 0x%.6x bytes] $entry\n", ++$upd_cur, $upd_tot, length($data));
  402. }
  403.  
  404. print "\n";
  405. print "[*] Regenerating local file database\n";
  406. $now_data = ScanFiles('.');
  407. WriteFile('.current', $now_data);
  408.  
  409.  
  410. sub Usage { 
  411.     print STDERR "  Usage: $0 [options]>\n";
  412.     print STDERR "Options:\n";
  413.     print STDERR "         -h             You're looking at me baby\n";
  414.     print STDERR "         -v             Display version information\n";
  415.     print STDERR "         -u             Perform an online update via metasploit.com\n";
  416.     print STDERR "         -s             Only display update tasks, do not actually download\n";
  417.     print STDERR "         -m             Show any files locally modified since last update\n";
  418.     print STDERR "         -a             Do not prompt, default to overwrite all files\n";
  419.     print STDERR "         -x             Do not require confirmation for non-SSL updates\n";
  420.     print STDERR "         -f             Disable ssl support entirely, use with -x to avoid warnings\n";
  421.     print STDERR "         -O             Removes the operating system name from the user agent\n";
  422.     print STDERR "         -p             Specifies a proxy: <http|socks4>:<hostname>:<port>\n";
  423.     
  424.     # Too buggy and dangerous to use
  425.     # print STDERR "         -U             Upgrade to a new major revision of the Framework\n";
  426.     # Developer options
  427.     # print STDERR "         -r             Rebuild the local version database (internal only)\n";
  428.     print "\n";
  429.     exit(0);
  430. }
  431.  
  432. sub ScanFiles {
  433.     my $dir = shift;
  434.     my $res;
  435.     my $hwn;
  436.     
  437.     opendir ($hwn, $dir) || return;
  438.     
  439.     while (defined(my $entry = readdir($hwn))) {
  440.         my $path = "$dir/$entry";
  441.  
  442.         # ignore all symlinks
  443.         next if -l $path;
  444.         
  445.         # ignore all leading dot files   
  446.         next if $entry =~ /^\./;
  447.         
  448.         # ignore the backup directories
  449.         next if $entry =~ /^backup_/;
  450.         
  451.         # recurse into directories
  452.         if (-d $path) {
  453.             $res .= ScanFiles($path);
  454.         } 
  455.         elsif (-f $path) {
  456.             $res .= HashFile($path)."\t$path\n";;
  457.         }
  458.     }
  459.     closedir($hwn);
  460.     return $res;   
  461. }
  462.  
  463. sub ScanDirs {
  464.     my $dir = shift;
  465.     my $dep = @_ ? shift() : 0;
  466.     my $res;
  467.     my $hwn;
  468.     
  469.     return if $dep == -1;
  470.     opendir ($hwn, $dir) || return;
  471.     
  472.     while (defined(my $entry = readdir($hwn))) {
  473.         my $path = "$dir/$entry";
  474.         
  475.         # ignore all symlinks
  476.         next if -l $path; 
  477.         
  478.         # ignore the backup directories
  479.         next if $entry =~ /^backup_/;
  480.         
  481.         # ignore all leading dot files   
  482.         next if $entry =~ /^\./;
  483.          
  484.         # recurse into directories
  485.         if (-d $path) {
  486.             $res .= "$path\n";
  487.             $res .= ScanDirs($path, $dep - 1);
  488.         }
  489.     }
  490.     closedir($hwn);
  491.     return $res;   
  492. }
  493.  
  494.  
  495.  
  496. sub CheckVersion {
  497.     my $data = DownloadFile($UPDATE_HOST, $UPDATE_PATH, $proxy);
  498.     my ($vers, $mtime) = split(/\s+/, $data);
  499.     return $vers;
  500. }
  501.  
  502. sub DownloadFile {
  503.     my $host = shift;
  504.     my $path = shift;
  505.     my $prox = shift;
  506.     
  507.     my $port = $SSL_SUPPORT ? 443 : 80;
  508.     my $data;
  509.     
  510.     $path = EscapeURI($path);
  511.     
  512.     my ($proxy_type, $proxy_host, $proxy_port);
  513.     if ($prox =~ m/^(socks4|http):([^:]+):(\d+)/) {
  514.         ($proxy_type, $proxy_host, $proxy_port) = ($1, $2, $3);
  515.     }
  516.     
  517.     if ($prox && ! $proxy_host) {
  518.         print STDERR "[*] Invalid proxy format ($prox), please use one of the following:\n";
  519.         print STDERR "\tSOCKS: socks4:<hostname|ip address>:<port>\n";
  520.         print STDERR "\t HTTP:   http:<hostname|ip address>:<port>\n\n";
  521.         exit(0);
  522.     }
  523.     
  524.     
  525.     my $sock = IO::Socket::INET->new
  526.     (
  527.         PeerAddr    => $proxy_host || $host,
  528.         PeerPort    => $proxy_port || $port,
  529.         Proto       => 'tcp',
  530.     );
  531.     
  532.     if (! $sock) {
  533.         print STDERR "[*] Could not connect to $host: $!\n";
  534.         exit(0);
  535.     }
  536.     
  537.     if ($proxy_type eq 'http') {
  538.         $sock->send("CONNECT ".$host.":".$port." HTTP/1.0\r\n\r\n");
  539.         
  540.         # Look for the HTTP response message from the Proxy server
  541.         my $sel = IO::Select->new($sock);
  542.         my $resp = '';
  543.         
  544.         if ($sel->can_read(5)) {
  545.             while (my $line = <$sock>)  {
  546.                 last if $line eq "\r\n";
  547.                 $resp .= $line;
  548.             }
  549.         } else {
  550.             print STDERR "[*] No reply received from the HTTP proxy\n";
  551.             exit(0);
  552.         }
  553.         
  554.         if ($resp !~ /HTTP\/1\.\d\s+2/) {
  555.             foreach my $line (split(/\r\n/, $resp)) {
  556.                 $line =~ s/\r|\n//g;
  557.                 $line =~ s/\e//g;
  558.                 print STDERR "[*] Proxy: " . $line . "\n";
  559.             }
  560.             print STDERR "[*] Connection failed\n";
  561.             exit(0);
  562.         }
  563.     }
  564.     
  565.     if ($proxy_type eq 'socks4') {
  566.         $sock->send("\x04\x01".pack('n',$port).gethostbyname($host)."\x00");
  567.         $sock->recv(my $res, 8);
  568.         
  569.         if (! $res || ($res && ord(substr($res,1,1)) != 90)) {
  570.             print STDERR "[*] Failed to established connection through socks4 proxy $proxy_host\n";
  571.             if (length($res)) {
  572.                 print STDERR "[*] Response: ". unpack("H*", $res) ."\n";
  573.             }
  574.             exit(0);
  575.         }    
  576.     }
  577.     
  578.     my $req = 
  579.         "GET $path HTTP/1.0\r\n".
  580.         "Host: ".$host.":".$port."\r\n".
  581.         "User-Agent: msfupdate/$REV $FRAMEWORK ($OPSYS)\r\n\r\n";
  582.     
  583.     if ($SSL_SUPPORT) { 
  584.     
  585.         # Reset the verified flag
  586.         $SSL_VERIFIED = 0;
  587.  
  588.         # Create SSL Context
  589.         my $ctx = Net::SSLeay::CTX_new();
  590.        
  591.         # Tell SSL to use the certificate in the docs directory 
  592.         Net::SSLeay::CTX_load_verify_locations($ctx, '', $SSL_CERTS);
  593.         
  594.         # Configure the SSL call-back to prevent MiTM
  595.         Net::SSLeay::CTX_set_verify($ctx, &Net::SSLeay::VERIFY_PEER, \&SSLVerify);
  596.                 
  597.         # Configure session for maximum interoperability
  598.         Net::SSLeay::CTX_set_options($ctx, &Net::SSLeay::OP_ALL);
  599.         
  600.         # Create a new SSL object with context
  601.         my $ssl = Net::SSLeay::new($ctx);
  602.  
  603.         # Bind the SSL descriptor to the socket
  604.         Net::SSLeay::set_fd($ssl, $sock->fileno);
  605.         
  606.         # Negotiate connection
  607.         my $sslConn = Net::SSLeay::connect($ssl);
  608.  
  609.         if ($sslConn <= 0) {
  610.             print STDERR "[*] SSL error:". Net::SSLeay::print_errs()."\n";
  611.             $sock->close;
  612.             return;
  613.         }
  614.         
  615.         Net::SSLeay::ssl_write_all($ssl, $req);
  616.         
  617.         my $cert = Net::SSLeay::get_peer_certificate($ssl);
  618.  
  619.         $data = Net::SSLeay::ssl_read_all($ssl);
  620.         
  621.         Net::SSLeay::free ($ssl);
  622.         Net::SSLeay::CTX_free ($ctx);
  623.         $sock->close;
  624.  
  625.         $data = ProcessHTTP($data);
  626.         return $data;
  627.     }
  628.     
  629.     $sock->send($req);
  630.     $sock->shutdown(1);
  631.     while (<$sock>) { $data .= $_ }
  632.     close ($sock);
  633.     
  634.     $data = ProcessHTTP($data);    
  635.     return $data;
  636. }
  637.  
  638. # Prevent MiTM attacks on the update downloads when run over SSL
  639. sub SSLVerify {
  640.     my ($ok, $x509_store_ctx) = @_;
  641.     my $cert = Net::SSLeay::X509_STORE_CTX_get_current_cert($x509_store_ctx);
  642.     
  643.     if ($cert) {
  644.         my $x509_issuer =  Net::SSLeay::X509_get_issuer_name($cert);
  645.         my $issuer = Net::SSLeay::X509_NAME_oneline($x509_issuer);
  646.         
  647.         # differences between openssl 0.9.6 vs 0.9.7 (thanks par!)
  648.         $issuer =~ s/Email/emailAddress/g;
  649.         
  650.         if ($ok && $issuer eq $SSL_ISSUER) {
  651.             $SSL_VERIFIED++;
  652.             return 1;
  653.         }
  654.     }
  655.    
  656.     return;
  657. }
  658.  
  659. sub ProcessHTTP {
  660.     my $http = shift;
  661.     my $idx = index($http, "\r\n\r\n");
  662.     return if -1 == $idx;
  663.     my $head = substr($http, 0, $idx);
  664.     my $body = substr($http, $idx + 4);
  665.     return if $head !~ /HTTP\/1..\s+2/;
  666.     return $body;  
  667. }
  668.  
  669. sub WriteFile {
  670.     my $file = shift;
  671.     my $data = shift;
  672.  
  673.     my @path = split(/\//, $file);
  674.     pop(@path);
  675.     
  676.     my $cdir = ".";
  677.     foreach (@path) {
  678.         $cdir .= "/".$_;
  679.         if (! -d $cdir) {
  680.             mkdir($cdir, 0755);
  681.         }
  682.     }
  683.     
  684.     open (my $out, ">$file") || return;
  685.     print $out $data;
  686.     close ($out);
  687. }
  688.  
  689. sub ReadFile {
  690.     my $path = shift;
  691.     my $data;
  692.     my $inp;
  693.     
  694.     open($inp, "<$path") || return;
  695.     while (<$inp>) { $data .= $_ }
  696.     close($inp);
  697.     
  698.     return $data;
  699. }
  700.  
  701. sub HashFile {
  702.     my $path = shift;
  703.     my $data = ReadFile($path);
  704.     return md5_hex($data);
  705. }
  706.  
  707. sub Hashit {
  708.     my $data = shift;
  709.     my $hash = {};
  710.     foreach my $line (split(/\n/, $data)) {
  711.         my ($md5, $path) = $line =~ m/^([^\s]+)\s+(.*)/g;
  712.         $hash->{$path} = $md5;
  713.     }
  714.     return $hash;
  715. }
  716.  
  717. sub Diff {
  718.     my $setA = shift;
  719.     my $setB = shift;
  720.     my $res;
  721.     
  722.     foreach (keys(%{$setA})) {
  723.         if (exists($setB->{$_})) {
  724.             if ($setA->{$_} ne $setB->{$_}) {
  725.                 $res->{$_} = 'Mod';
  726.             }
  727.         } 
  728.         else {
  729.             $res->{$_} = 'Del';
  730.         }
  731.     }
  732.     
  733.     foreach (keys(%{$setB})) {
  734.         if (! exists($setA->{$_})) {
  735.             $res->{$_} = 'New';
  736.         }
  737.     }
  738.     
  739.     return $res;
  740. }
  741.  
  742. sub EscapeURI {
  743.     my $path = shift;
  744.     my %escapes = ();
  745.     for (0..255) { $escapes{chr($_)} = sprintf("%%%02X", $_) }
  746.     $path =~ s/([^A-Za-z0-9\-_.!~*'()\/])/$escapes{$1}/eg;
  747.     return $path;
  748. }
  749.  
  750. sub BrokenUTF8 {
  751.     if ( $] >= 5.008 && $] < 5.008002 )
  752.      {
  753.          my $badver;
  754.         
  755.         # Check LANG first
  756.         $badver = ($ENV{'LANG'} =~ /utf/i) ? 1 : 0;
  757.         
  758.         # LC_ALL overrides LANG if its set
  759.         if (defined($ENV{'LC_ALL'})) {
  760.             $badver = ($ENV{'LC_ALL'} =~ /utf/i) ? 1 : 0;
  761.         }
  762.         
  763.         return if ! $badver;
  764.      
  765.         print STDERR qq|
  766. [*] This version of Perl ($]) contains a buggy utf-8 implementation. If you
  767.     would like to use this version with the Metasploit Framework, you must
  768.     set the LC_ALL environment variable to 'C'. For example:
  769.  
  770.     \$ export LC_ALL=C; ./msfconsole
  771.     
  772. |;
  773.     exit(0);
  774.     }
  775. }
  776.